package com.dwjm.exam.stu_list;

import com.dwjm.utils.CommonResult;
import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

/**
 * 处理学生信息的控制器，该类继承自 HttpServlet，用于处理与学生信息相关的 HTTP 请求。
 * 它能处理学生信息的查询、添加、删除等操作，并通过 DAO 层与数据库交互。
 */
@WebServlet("/student")
public class InguireHandler extends HttpServlet {
    // 数据访问对象，用于与数据库进行交互，执行学生信息的增删改查操作
    private InquireDao abcDao;
    // 时间格式化工具，用于将字符串类型的日期转换为 Date 类型，格式为 "yyyy-MM-dd"
    private SimpleDateFormat timeFormat;
    // JSON 工具，用于将 Java 对象转换为 JSON 字符串，以便在 HTTP 响应中返回
    private Gson jsonTool;

    /**
     * 初始化 Servlet 时调用该方法，用于初始化数据访问对象、时间格式化工具和 JSON 工具。
     * @throws ServletException 如果在初始化过程中出现问题，抛出 ServletException
     */
    @Override
    public void init() throws ServletException {
        // 初始化数据访问对象
        abcDao = new InquireDaolmpl();
        // 初始化时间格式化工具
        timeFormat = new SimpleDateFormat("yyyy-MM-dd");
        // 初始化 JSON 工具
        jsonTool = new Gson();
    }

    /**
     * 处理 HTTP GET 请求，根据请求的路径执行不同的操作，如获取所有学生、搜索学生或获取单个学生信息。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws ServletException 如果在处理请求过程中出现 Servlet 相关的问题，抛出 ServletException
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 获取请求的路径信息
        String path = req.getPathInfo();
        if (path == null || path.equals("/")) {
            // 如果路径为空或为根路径，调用 getAllStu 方法获取所有学生信息
            getAllStu(req, resp);
        } else if (path.startsWith("/search")) {
            // 如果路径以 "/search" 开头，调用 searchStu 方法搜索学生信息
            searchStu(req, resp);
        } else {
            // 否则，从路径中提取学生 ID，调用 getStuById 方法获取单个学生信息
            String stuId = path.substring(1);
            getStuById(stuId, resp);
        }
    }

    /**
     * 处理 HTTP POST 请求，根据请求的路径执行添加新学生的操作。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws ServletException 如果在处理请求过程中出现 Servlet 相关的问题，抛出 ServletException
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 获取请求的路径信息
        String path = req.getPathInfo();
        if (path == null || path.equals("/")) {
            // 如果路径为空或为根路径，调用 addStu 方法添加新学生
            addStu(req, resp);
        }
    }

    /**
     * 处理 HTTP DELETE 请求，根据请求的路径执行删除学生的操作。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws ServletException 如果在处理请求过程中出现 Servlet 相关的问题，抛出 ServletException
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 获取请求的路径信息
        String path = req.getPathInfo();
        if (path != null && path.length() > 1) {
            // 如果路径不为空且长度大于 1，从路径中提取学生 ID，调用 delStu 方法删除学生
            String stuId = path.substring(1);
            delStu(stuId, resp);
        }
    }

    /**
     * 获取所有学生信息，并将结果以 JSON 格式返回给客户端。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void getAllStu(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        try {
            // 调用数据访问对象的 getAllStudents 方法获取所有学生信息
            List<Student> stuList = abcDao.getAllStudents();
            // 调用 sendResponse 方法将成功结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.success(stuList));
        } catch (Exception e) {
            // 如果出现异常，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.fail(500, "获取学生列表出错：" + e.getMessage()));
        }
    }

    /**
     * 根据关键词搜索学生信息，并将结果以 JSON 格式返回给客户端。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void searchStu(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        // 从请求参数中获取搜索关键词
        String keyword = req.getParameter("q");
        if (keyword != null && !keyword.trim().isEmpty()) {
            try {
                // 如果关键词不为空，调用数据访问对象的 queryStudents 方法搜索学生信息
                List<Student> stuList = abcDao.queryStudents(keyword.trim());
                // 调用 sendResponse 方法将成功结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.success(stuList));
            } catch (Exception e) {
                // 如果出现异常，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.fail(500, "搜索学生出错：" + e.getMessage()));
            }
        } else {
            // 如果关键词为空，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.fail(400, "搜索关键词不能为空"));
        }
    }

    /**
     * 根据学生 ID 获取单个学生信息，并将结果以 JSON 格式返回给客户端。
     * @param stuId 学生的 ID
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void getStuById(String stuId, HttpServletResponse resp)
            throws IOException {
        try {
            // 调用数据访问对象的 getStudentById 方法获取单个学生信息
            Student stu = abcDao.getStudentById(stuId);
            if (stu != null) {
                // 如果学生信息存在，调用 sendResponse 方法将成功结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.success(stu));
            } else {
                // 如果学生信息不存在，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.fail(404, "找不到这个学生"));
            }
        } catch (Exception e) {
            // 如果出现异常，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.fail(500, "获取学生信息出错：" + e.getMessage()));
        }
    }

    /**
     * 添加新学生信息，并将结果以 JSON 格式返回给客户端。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void addStu(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        try {
            // 从请求中获取学生信息
            Student stu = getStuFromReq(req);
            // 调用数据访问对象的 addStudent 方法添加新学生
            int result = abcDao.addStudent(stu);
            if (result > 0) {
                // 如果添加成功，调用 sendResponse 方法将成功结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.success(stu));
            } else {
                // 如果添加失败，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.fail(500, "添加学生失败"));
            }
        } catch (Exception e) {
            // 如果出现异常，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.fail(400, "添加学生出错：" + e.getMessage()));
        }
    }

    /**
     * 根据学生 ID 删除学生信息，并将结果以 JSON 格式返回给客户端。
     * @param stuId 学生的 ID
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void delStu(String stuId, HttpServletResponse resp)
            throws IOException {
        try {
            // 调用数据访问对象的 deleteStudent 方法删除学生信息
            int result = abcDao.deleteStudent(stuId);
            if (result > 0) {
                // 如果删除成功，调用 sendResponse 方法将成功结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.success());
            } else {
                // 如果删除失败，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
                sendResponse(resp, CommonResult.fail(404, "找不到要删除的学生"));
            }
        } catch (Exception e) {
            // 如果出现异常，调用 sendResponse 方法将失败结果以 JSON 格式返回给客户端
            sendResponse(resp, CommonResult.fail(500, "删除学生出错：" + e.getMessage()));
        }
    }

    /**
     * 从 HTTP 请求中提取学生信息，并创建一个 Student 对象。
     * @param req HTTP 请求对象，包含客户端的请求信息
     * @return 包含学生信息的 Student 对象
     * @throws ParseException 如果在日期解析过程中出现问题，抛出 ParseException
     */
    private Student getStuFromReq(HttpServletRequest req) throws ParseException {
        // 创建一个新的 Student 对象
        Student stu = new Student();
        // 从请求参数中获取学生 ID 并设置到 Student 对象中
        stu.setStudentId(req.getParameter("studentId"));
        // 从请求参数中获取学生姓名并设置到 Student 对象中
        stu.setName(req.getParameter("name"));
        // 从请求参数中获取学生性别并设置到 Student 对象中
        stu.setGender(req.getParameter("gender"));
        // 从请求参数中获取学生出生日期
        String birthStr = req.getParameter("birthDate");
        if (birthStr != null && !birthStr.trim().isEmpty()) {
            // 如果出生日期不为空，将其解析为 Date 类型并设置到 Student 对象中
            stu.setBirthDate(timeFormat.parse(birthStr));
        }
        // 从请求参数中获取学生身份证号并设置到 Student 对象中
        stu.setIdCard(req.getParameter("idCard"));
        // 从请求参数中获取学生所在学院并设置到 Student 对象中
        stu.setCollege(req.getParameter("college"));
        // 从请求参数中获取学生所学专业并设置到 Student 对象中
        stu.setMajor(req.getParameter("major"));
        // 从请求参数中获取学生所在班级并设置到 Student 对象中
        stu.setClassName(req.getParameter("className"));
        // 从请求参数中获取学生状态并设置到 Student 对象中
        stu.setStatus(req.getParameter("status"));
        // 从请求参数中获取学生宿舍 ID 并设置到 Student 对象中
        stu.setDormId(req.getParameter("dormId"));
        // 从请求参数中获取学生床位号并设置到 Student 对象中
        stu.setBedNumber(req.getParameter("bedNumber"));
        // 从请求参数中获取学生联系电话并设置到 Student 对象中
        stu.setPhone(req.getParameter("phone"));
        // 从请求参数中获取学生电子邮箱并设置到 Student 对象中
        stu.setEmail(req.getParameter("email"));
        // 从请求参数中获取学生紧急联系人信息并设置到 Student 对象中
        stu.setEmergencyContact(req.getParameter("emergencyContact"));
        // 从请求参数中获取学生用户名并设置到 Student 对象中
        stu.setUsername(req.getParameter("username"));
        // 从请求参数中获取学生密码并设置到 Student 对象中
        stu.setPassword(req.getParameter("password"));
        return stu;
    }

    /**
     * 将处理结果以 JSON 格式发送给客户端。
     * @param resp HTTP 响应对象，用于向客户端发送响应
     * @param result 处理结果对象，包含处理结果信息
     * @throws IOException 如果在输入输出过程中出现问题，抛出 IOException
     */
    private void sendResponse(HttpServletResponse resp, CommonResult<?> result) throws IOException {
        // 设置响应的内容类型为 JSON
        resp.setContentType("application/json");
        // 设置响应的字符编码为 UTF-8
        resp.setCharacterEncoding("UTF-8");
        // 获取响应的输出流
        PrintWriter writer = resp.getWriter();
        // 将处理结果对象转换为 JSON 字符串并写入输出流
        writer.println(jsonTool.toJson(result));
        // 刷新输出流
        writer.flush();
    }
}